#include "FreeCamera.h"

namespace PeanutQuest {

    FreeCamera::FreeCamera(std::string id) : Entity(id) {
		//posicao inicial
		position[0] = position[0]+20;
		position[1] = position[1]-2;
		position[2] = position[2]-10;
		//definicao dos eixos
		front.set(1,0,0);
		side.set(0,0,-1);
		up.set(0,1,0);
		translate_front = false;
		translate_back = false;
		 //orientacao inicial
		_orientation.setRotationDeg(90,cg::Vector3d(0,1,0));
		_isGoAhead = false;
		_isGoBack = false;
		_isTurnLeft = false;
		_isTurnRight = false;
		
		_linearVelocity = 5;
		_angularVelocity = 50;

		active = false;
	}
    FreeCamera::~FreeCamera() {
	}
    void FreeCamera::init() {
		cg::tWindowInfo win = cg::Manager::instance()->getApp()->getWindowInfo();
		_winWidth = win.width;
		_winHeight = win.height;
    }

	bool FreeCamera::getActive() {
		return active;
	}

	void FreeCamera::turnActive() {
		active = !active;
	}

	void FreeCamera::goAhead() { _isGoAhead = true; }
	void FreeCamera::goBack() { _isGoBack = true; }
	void FreeCamera::turnLeft() { _isTurnLeft = true; }
	void FreeCamera::turnRight() { _isTurnRight = true; }

	void FreeCamera::update(unsigned long elapsed_millis){

		double elapsed_seconds = elapsed_millis / (double)1000;

		if(cg::KeyBuffer::instance()->isKeyDown('w') || 
			cg::KeyBuffer::instance()->isSpecialKeyDown(GLUT_KEY_UP)) {
				goAhead();
		}
		if(cg::KeyBuffer::instance()->isKeyDown('s') ||
			cg::KeyBuffer::instance()->isSpecialKeyDown(GLUT_KEY_DOWN)) {
				goBack();
		}
		if(cg::KeyBuffer::instance()->isKeyDown('a')||
			cg::KeyBuffer::instance()->isSpecialKeyDown(GLUT_KEY_LEFT)) {
				turnLeft();
		}
		if(cg::KeyBuffer::instance()->isKeyDown('d')||
			cg::KeyBuffer::instance()->isSpecialKeyDown(GLUT_KEY_RIGHT)) {
				turnRight();
		}
		
		step(elapsed_seconds);

	}

	void FreeCamera::step(double elapsed_seconds) {

		if(_isGoAhead) {
			position += front * _linearVelocity * elapsed_seconds;
			_isGoAhead = false;
		}
		if(_isGoBack) {
			position -= front * _linearVelocity * elapsed_seconds;
			_isGoBack = false;
		}
		if(_isTurnLeft) {
			rotate(elapsed_seconds,-1,up,front,side);
			_isTurnLeft = false;
		}
		if(_isTurnRight) {
			rotate(elapsed_seconds,1,up,front,side);
			_isTurnRight = false;
		}

		_orientation.getGLMatrix(_rotationMatrix);
	}

	inline
	void FreeCamera::rotate(double elapsed_seconds, int direction, 
						   cg::Vector3d axis, cg::Vector3d& v1, cg::Vector3d& v2) 
	{
		_q.setRotationDeg(direction * _angularVelocity * elapsed_seconds,axis);
		v1 = apply(_q,v1);
		v2 = apply(_q,v2);
		_orientation = _q * _orientation;
		
	}

    void FreeCamera::draw() {
		glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
		gluPerspective(60,_winWidth/(double)_winHeight,1.0,100.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

		glMultMatrixd(_rotationMatrix);
		glTranslated(-position[0],position[1],position[2]);
	}

	void FreeCamera::onReshape(int width, int height) {
		_winWidth = width;
		_winHeight = height;
	}
}
